import jwt from 'jsonwebtoken';
import FetchStream from './FetchStream.js';

const GLM_4 = 'https://open.bigmodel.cn/api/paas/v4/chat/completions';

// 最大返回token数
const MAX_TOKENS = 8192;

// 个人key，仅供demo
const API_KEY = 'ca2906637803979ad0d02ff6f146fe13.8NeNd1psO27FyZmn';
const [ID, SECRET] = API_KEY.split('.');
function generate_token(exp_seconds) {
    const payload = {
        api_key: ID,
        exp: Date.now() + exp_seconds * 1000,
        timestamp: Date.now() * 1000
    }

    return jwt.sign(
        payload,
        SECRET,
        {
            algorithm: 'HS256',
            header: {
                alg: 'HS256',
                sign_type: 'SIGN'
            }
        }
    )
}

// 记录每次请求的返回结果,用于多轮询问
const CATCHE_DB = {
    /*
    
    'conversation_id': {
        create_time: ''
        history: [] 
    }
    */

};


/**
 *      tool: 'c2rust',
 *      code: '',
 *      prompt: '',
 *      id: '', // 用于标识不同的的对话
*/

export async function chatglm(config) {
    console.log('[chatglm] start transcode...');
    return new Promise(async (resolve, reject) => {

        if (!config.id) return reject("id required");

        if (!CATCHE_DB[config.id]) {
            CATCHE_DB[config.id] = {
                create_time: Date.now(),
                history: [
                    { "role": "system", "content": "你现在是C/C++和Rust的资深专家，工作是将C/C++代码转换为Rust代码，在转换代码时，需要精确匹配C++的行为，要求尽可能使用Rust标准库实现，并尽可能不使用unsafe关键字，每次转换，你都需要给出完整可执行的Rust代码，不要做额外解释。" },
                    // {"role": "user", "content": config.prompt || '请将下列代码转换为Rust代码：\n' + config.code}
                ]
            }
        }

        if (config.prompt) {
            CATCHE_DB[config.id].history.push({ "role": "user", "content": config.prompt })
        } else {
            CATCHE_DB[config.id].history.push({ "role": "user", "content": '请将下列代码转换为Rust代码：\n' + config.code })
        }



        // console.log('Config:', config);
        // console.log('History: ', history);

        // const prompt = `${code}\n将上述C语言代码转换为Rust语言实现，要求尽量使用rust标准库实现，并尽量不使用unsafe关键字。你只需要返回Rust代码，不用额外解释。`
        // const prompt =  || "你现在是一名资深的c++和Rust的工程师直到我指定切换角色之前你的角色不变，同时代码转换的时候直接给出转换代码而且不要输出其他的内容也不要对代码做额外的解释，要求尽量使用rust标准库实现，并尽量不使用unsafe关键字：```rust" + config.code + "```"
        // const prompt = config.prompt

        // 使用code作为seed，相同的代码的id将会相同，意味着相同的代码将共享一个历史
        // const chat_id = generateChatIdFrom(config.code);

        // let messages = [
        //     {"role": "system", "content": "你现在是C/C++和Rust的资深专家，工作是将C/C++代码转换为Rust代码，在转译代码时，要求尽量使用Rust标准库实现，并尽量不使用unsafe关键字，不要做额外解释。"},
        //     {"role": "user", "content": config.prompt || '请将下列代码转换为Rust代码：\n' + config.code}
        // ];
        // if (!history[chat_id]) {
        //     history[chat_id] = [...messages];
        // } else {
        //     const d = {"role": "user", "content": config.prompt || '请将下列C代码转换为Rust代码：\n' + config.code}
        //     history[chat_id].push(d);
        //     messages = history[chat_id];
        // }

        const messages = CATCHE_DB[config.id].history;
        console.log(`chatglm messages[${config.id}] length: `, messages.length);

        const data = {
            model: 'glm-4',
            max_tokens: MAX_TOKENS,
            messages,
        }

        let answer;
        try {
            const response = await fetch(GLM_4, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": generate_token(60 * 60 * 24)
                },
                body: JSON.stringify(data),
            });
    
            answer = await response.json();
        } catch (e) {
            console.error('[chatlm] API 连接错误:', e);
            reject('获取数据失败。');
            return;
        }

        if (answer.error) {
            return reject(answer.error.message);
        }

        // console.log(answer.choices[0].message.content);

        // 将回答加入历史记录
        CATCHE_DB[config.id].history.push({ "role": "assistant", "content": answer.choices[0].message.content });

        const reg = /```rust\n([\s\S]*?)```/g;

        let result = '';
        const codes = [];
        while (result = reg.exec(answer.choices[0].message.content)) {
            codes.push(result[1]);
        }
        // const rust_code = answer.choices[0].message.content.match(/```rust\n([\s\S]*)```/)[1];

        // return codes.join('\n');
        resolve((codes[0] || '').trim());
    })
}

export async function chatglm_stream(config, res) {

    if (!config.id) {
        res.send({
            status: 1,
            error: '缺少conversation id'
        });
        return;
    }

    if (!CATCHE_DB[config.id]) {
        CATCHE_DB[config.id] = {
            create_time: Date.now(),
            history: [
                { "role": "system", "content": "你现在是C/C++和Rust的资深专家，工作是将C/C++代码转换为Rust代码，在转换代码时，需要精确匹配C++的行为，要求尽可能使用Rust标准库实现，并尽可能不使用unsafe关键字，每次转换，你都需要给出完整可执行的Rust代码，不要做额外解释。" },
            ]
        }
    }

    if (config.prompt) {
        CATCHE_DB[config.id].history.push({ "role": "user", "content": config.prompt })
    } else {
        CATCHE_DB[config.id].history.push({ "role": "user", "content": '请将下列代码转换为Rust代码：\n' + config.code })
    }

    const messages = CATCHE_DB[config.id].history;
    console.log(`chatglm messages[${config.id}] length: `, messages.length);

    const data = {
        model: 'glm-4',
        messages,
        max_tokens: MAX_TOKENS,
        stream: true
    }

    let content = ''; // 拼接每一个分块数据
    const fetchStream = new FetchStream({
        url: GLM_4,
        requestInit: { // fetch 配置项
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Accept": "text/event-stream",
                "Authorization": generate_token(60 * 60 * 24)
            },
            body: JSON.stringify(data),
        },
        onmessage: (dataList, _index) => {

            for (const item of dataList) {
                const data_str = item.split("data: ")[1];
                if (data_str && data_str !== '[DONE]') {
                    try {
                        const data_json = JSON.parse(data_str);
                        content += data_json.choices[0].delta.content;

                        try {
                            res.write(JSON.stringify({
                                status: 0,
                                content: data_json.choices[0].delta.content,
                                id: config.id,
                            }) + '\n\n');
                        } catch (e) {
                            console.error(e);
                        }
                    } catch (_) {
                        // 将解析错误的内容返回缓存，在下一次消息中添加到新消息的头部
                        return item;
                    }
                }
            }
        },
        ondone: () => {
            // console.log('done!', content);
            // 将回答加入历史记录
            CATCHE_DB[config.id].history.push({ "role": "assistant", "content": content });
            res.write('[DONE]');
            res.end();
        },
        ontimeout: () => {
            console.log('timeout!');
        }
    });
}